import networkx as nx
from timer import Timerx
from itertools import izip
import numpy as np

def read_graph(file_path, delimiter=' ', convert_string_to_int = True):
    G = nx.Graph()
    
    with open(file_path) as edges_file:
        for line in edges_file:
            source, target = line.rstrip().split(delimiter)
            if (convert_string_to_int):
                G.add_edge(int(source), int(target))
            else:
                G.add_edge(source, target)
    
    return G

def build_U(nodes_list):
    """
    Returns a list U which is the universal edges set that contains 
    every possible edge that can be in the graph. 
    The size of this set N*(N-1)/2 where N is the number of nodes/vertices.
    """
    
    N = len(nodes_list)
    U_size = (N*(N-1))/2
    U = np.zeros((U_size,2))
    
    j = 0
    for i, node1 in enumerate(nodes_list):
        for node2 in nodes_list[i+1:]:
            edge = (node1,node2)
            U[j] = edge
            j += 1
            
    #Old fast but memory consuming way
#     U = list()
#  
#     for i, node1 in enumerate(nodes_list):
#         for node2 in nodes_list[i+1:]:
#             edge = (node1,node2)
#             U.append(edge)
    
    return U

def build_Y(G, U):
    """
    Builds the Y ground-truth list that contains a label
    for each edge in the universal to indicate if the edge
    really exists in the graph or not.
    
    Parameters:
    G: the Networkx graph.
    U: the universal edges set that contains every possible edge in the graph.
    """
    N = len(U)
    Y = np.zeros(N)
    
    for i, edge in enumerate(U):
        node1 = edge[0]
        node2 = edge[1]
        if G.has_edge(node1,node2):
            Y[i] = 1
            
#     Y = list()
#     
#     for edge in U:
#         node1 = edge[0]
#         node2 = edge[1]
#         if G.has_edge(node1,node2):
#             Y.append(1)
#         else:
#             Y.append(0)
    
    return Y

def add_feature(data, U, S, nodes_list):
    """
    Extends the data matrix with a column that represents 
    a new feature.
    
    Parameters:
    data: the data matrix (usually called X in sci-kit).
    U: the universal edges list (set).
    S: the similarity matrix that holds the similarities between each
       node in the graph.
       
    Returns the data extended with a new column.
    """
    
    nodes = {}
    for i, node in enumerate(nodes_list):
        nodes[node] = i
    
    N = len(U)
    feature = np.zeros(N)
    
    for i, edge in enumerate(U):
        node1 = edge[0]
        node2 = edge[1]
        node1_index = nodes[node1]
        node2_index = nodes[node2]
        feature[i] = S[node1_index, node2_index]

    if data == None:
        data = np.reshape(feature, (-1,1))
    else:
        data = np.column_stack([data, feature])

    return data













